import sys, os

from liwe.module import LiweModule
from os3.utils.image_handler import ImageHandler
from PIL import Image
from PIL.ExifTags import TAGS

class Gallery ( LiweModule ):

	GALLERY_NAME_FIELDS = [ 'id', 'name', 'w', 'h', 'created' ]
	GALLERY_FIELDS = [ 'id', 'id_gal', 'uid', 'pos', 'created', 'title', 'name', 'ext', 'kind', 'descr', 'fsize', 'shot_date', 'orient', 'dx', 'dy', 'lat', 'lng' ]

        def __init__ ( self, liwe ):
                super ( Gallery, self ).__init__ ( liwe, "gallery" )

                self.dbm = self.liwe.dbm
		self.THUMB_PATH = self.cfg.get ( 'thumb.path', 'site/gallery/thumbs' )

		self.IMAGE_PATH = self.cfg.get ( 'image.path', 'site/gallery/images' )

	def _get_cfg ( self, id_gal ):

		THUMB_WIDTH= self.cfg.get ( 'thumb.w', 150 ) 
		THUMB_HEIGHT= self.cfg.get ( 'thumb.h', 150 )
		IMAGE_WIDTH = self.cfg.get ( 'image.w', 0 )
		IMAGE_HEIGHT = self.cfg.get ( 'image.h', 0 )

		if id_gal:
			thumb_sizes = self.dbm.single_row ( 'gallery_name', [ 'w', 'h' ] , 'id = %s' % id_gal )
			if thumb_sizes:
				THUMB_WIDTH= thumb_sizes [ 'w' ]  
				THUMB_HEIGHT= thumb_sizes [ 'h' ] 
				
		ICONS_PER_PAGE_SMALL = self.cfg.get ( 'icons_per_page.small', 20 )
		ICONS_PER_PAGE_FULL = self.cfg.get ( 'icons_per_page.full', 20 )
		ORDER_BY = self.cfg.get ( 'order_by', 'created' )		
		
		liwe_cfg = {
				"DS_CFG" : [
						{
						"ICONS_PER_PAGE_SMALL" : ICONS_PER_PAGE_SMALL,
						"ICONS_PER_PAGE_FULL" : ICONS_PER_PAGE_FULL,
						"ORDER_BY" : ORDER_BY
						}	
					   ],
			  
				"IMG_SETTINGS" : [
							{
							'path'  : self.IMAGE_PATH,
							'width' : IMAGE_WIDTH,
							'height': IMAGE_HEIGHT
							},
							{
							'path'  : self.THUMB_PATH,
							'width' : THUMB_WIDTH,
							'height': THUMB_HEIGHT 
							}
					         ]
			   }
		
		return liwe_cfg

	def _parse_exif ( self, tmp_name, img_id ):

		ex = {}
		dct = {}

		try:
			i = Image.open ( tmp_name )

			ex [ "Width" ] = i.size [ 0 ]
			ex [ "Height" ] = i.size [ 1 ]

			info = i._getexif ()

			if info: 
				for tag, value in info.items():
					decoded = TAGS.get ( tag, tag )
					ex [ decoded ] = value
				#sys.stderr.write ( "\n---------------GALLERY _parse_exif: info decoded  %s \n" % repr ( ex ) )
		except:
			pass

		size = os.stat ( tmp_name ) [ 6 ]

		try:
			os.remove ( tmp_name )
		except:
			pass

		shot_date = ex.get ( "DateTimeOriginal" ) or "*NOW()"
		orient = int ( ex.get ( "Orientation", 0 ) )
		if orient < 5:
			orient = 'o'
		else:
			orient = 'v'

		dct [ "fsize" ] = size
		dct [ "shot_date" ] = shot_date
		dct [ "orient" ] = orient
		dct [ "dx" ] = ex.get ( "Width", 0 )
		dct [ "dy" ] = ex.get ( "Height", 0 )

		gps = ex.get ( "GPSInfo" )
		if gps:
			lat = gps.get ( "GPSLatitude" )
			lng = gps.get ( "GPSLongitude" )
			if lat != None: dct [ "lat" ] = lat
			if lng != None: dct [ "lng" ] = lng

		self.dbm.update ( "gallery", dct, "id = %s" % img_id )

	#{{{ Gestione Gallery_name
	# ..function:: Gallery.add_gal ( self, id, name, w , h )
	#	Add or Update row in gallery_name table
	#	Return id added or modified
	#	:param	id:		gallery unique id 
	#	:param	name:		gallery name
	#	:param	w:		resizing width of the uploaded images
	#	:param	h:		resizing height of the uploaded images
	def add_gal ( self, iid = 0, name = '', w = 0 , h = 0 ):
	
                vals = { 'id' :  iid,
                        'name'  : name,
                        'w' : w,
                        'h' : h,
                        'created' : '*NOW()'
                        }

                if not iid:
                        if "id" in vals: del vals [ 'id' ]
                        self.dbm.insert ( 'gallery_name' , vals )
                        last_id = self.dbm.insert_id ( )
                        return last_id
		
		vals.pop ( 'h' )
		vals.pop ( 'w' )	
                self.dbm.update ( 'gallery_name', vals, "id = %s" % iid )
                return iid

	# ..function:: Gallery.get_gallery ( self, id, name )
	#	return corrensponding row filtred by id or name for table gallery_name
	#	:param id:	id of config
	#	:param name:	name of config
	def get_gallery ( self, iid = 0, name = '' ):
		res = []
		if( not iid ) and  ( not name ) :  return res
		conds = []
		if iid : conds.append ( 'id = %s ' % iid )
		if name : conds.append ( "name = '%s' " % name )
		
		res = self.dbm.single_row ( 'gallery_name', self.GALLERY_NAME_FIELDS , ' AND '.join ( conds ) )
		return res

	# ..function:: Gallery.list_galleries ( self )
	#	return dictionary that contain rows and totrows in gallery_name
	#	:param start_point:	start point for LIMIT condition
	#	:param do_count:	number of row for limit condition
	def list_galleries ( self, quant=10, start_point = 0,  do_count = 0, ):

		tot_rows=0
		if do_count:
			tot_rows = self.dbm.count ( 'gallery_name', self.GALLERY_NAME_FIELDS )
		
		extra = ''
		if quant:
			extra = 'LIMIT %s, %s' % ( start_point, quant )
		rows = self.dbm.all_rows ( 'gallery_name',  self.GALLERY_NAME_FIELDS, extras = extra ) 
		if not rows: rows = []
		return { "rows" : rows, "tot_rows" : tot_rows }

	# ..function:: Gallery.del_gal ( self , ids )
	#	delete selected gallery and all its images 
	#	:param ids:	string width single id or multiple separeted |
	def del_gal ( self, ids = '' ):

		if not ids: return
		id_lst = ids.split ( '|' )
		for iid in id_lst:
			
			lst = self.dbm.all_rows ( "gallery", [ 'id' ] , "id_gal = %s" % iid )
			if lst:
				ids_sc = '|'.join ( [ str( x['id'] ) for x in lst ])			
				self.delete ( ids_sc )
			self.dbm.delete ( "gallery_name", "id = %s " % iid )
		return
		
	#}}}



	#..function:: Gallery.add_image ( self, id, id_gal, pos, descr , file_obj )
	#	add o update single row in gallery table, save image with  H and W for the assigned configuration
	#	:param id:	image id
	#	:param id_gal	gallery id
	#	:param pos 	position
	#	:param descr	image description	
	def add_image ( self, iid = 0, id_gal = 0, pos = 0, title = '', descr = '', file_obj = None ):
	
		iid = int ( iid )	
		dct = {
			'id_gal'	: id_gal,
			'pos'		: pos,
			'title'		: title,
			'descr'		: descr,
			'created'	: '*NOW()'
			}

		sys.stderr.write ( "\n ----------  GALLERY add_image: param iid %s\n" % str ( type ( iid  ) ) )
		if file_obj:
			file_split = os.path.splitext ( file_obj [ 'filename' ] )
			dct [ 'name' ] = file_split [ 0 ]
			dct [ 'ext' ]  = file_split [ 1 ]
			dct [ 'kind' ] = file_obj [ 'type' ]
		#INSERT
		if not iid:	
			dct [ 'id' ] =  ''
			self.dbm.insert ( "gallery", dct, debug = self.debug () )
			iid = self.dbm.insert_id ()
			sys.stderr.write ( "\n ----------  GALLERY add_image: last inserted iid %s\n" % iid )
		else:		
		#UPDATE
			fields = self.GALLERY_FIELDS 
			chk = self.dbm.single_row ( "gallery", fields,  "id = %s" % iid )
			if chk and file_obj:
				#remove file if it does exits
				self._remove_file ( iid = chk [ 'id' ] )

			self.dbm.update ( "gallery", dct, "id = %s" % iid )
		#salva file
		self._save_file ( iid, id_gal, file_obj ) 
		

	#..function:: Gallery._save_file ( id, file_obj )
	#	save file whith H W specified in id_conf
	#	:param id	ID's gallery
	#	:param id_conf	ID's gallery_conf
	#	:param file_obj	file to save
	def _save_file ( self, iid = 0, id_gal = 0, file_obj = None ):

		if not iid or not file_obj or not id_gal: return

		liwe_cfg = self._get_cfg ( id_gal ) 
		cfg = liwe_cfg [ 'IMG_SETTINGS' ]

		name = file_obj [ 'filename' ]
		fil = file_obj [ 'file' ]
		fil.seek ( 0, os.SEEK_END )
		size = fil.tell ()
		fil.seek ( 0 )

		split = os.path.splitext ( file_obj [ 'filename' ] )
		if split:
			ext = split [ 1 ] 
		else:
			ext = ""

		ext = ext.lower ()

		fout_name = os.path.join ( cfg [ 0 ][ 'path' ] , "temp_%s%s" % ( iid, ext ) )

		fout = open ( fout_name, "wb" )
		fout.write ( fil.read () )
		fout.close ()

		self._create_thumb_image ( iid, cfg, fout_name )
		self._parse_exif ( fout_name, iid ) 
		self._remove_file ( name =  "temp_%s%s" % ( iid, ext ) )
	
	#..function:: Gallery._create_thumb_image ( path_name, id, gal, full_dest_name )
	#	Scale and save image in site/gallery/images
	#	:param path_name	path to stock image scaled
	#	:param id		ID gallery
	#	:param gal		Configiration row from gallery_name table
	#	:param full_dest_name	Original file path
        def _create_thumb_image ( self, iid, cfg, full_dest_name ):

                ih = ImageHandler ()
                im = ih.load ( full_dest_name )
                im.toRGB ()

		for c in cfg:	
			_width = c [ 'width' ]
			_height = c [ 'height' ] 
			
			sys.stderr.write ( "\n---------------GALLERY _create_thumb_image: _width %s, _height %s\n" % ( _width, _height ) )
			if _height or _width: 
		
				im.scale ( _width, _height )

			im.save ( os.path.join ( c [ 'path' ], "%s.jpg" % iid ), "JPEG" )


	#..function:: Gallery._def_mime_type ( path_name )
	#	Return file's mime
	#	:param path_name	path of file to get mime 
        def _define_mime_type ( self, path_name = '' ):
                mimetypes.init ()
                mime = mimetypes.guess_type ( path_name )
                return mime

	#..function:: Gallery._remove_file
	#	Remove file from file system /site/gallery/images
	#	:param id	ID's gallery
	#	:param ext	file extension
	#	:param name	file name
	def _remove_file ( self, iid = '',  ext = '.jpg', name = '', path = '' ):
		
		if not name:
			name =  "%s%s" % ( iid, ext )
		if not path:
			path =  [ self.IMAGE_PATH, self.THUMB_PATH ]
		for p in path:
			path_name =  os.path.join ( p, "%s" % name )
			try:
				os.remove ( path_name )
			except:
				return 2

	#..function:: Gallery.delete ( ids )
	#	Remove row/s from gallery table, remove image
	#	:param ids	ID's or IDs 
	def delete ( self, ids = '' ):
		
		if not ids: return

		id_lst = ids.split ( '|' )
		for iid in id_lst:
			self._remove_file ( iid = iid )
			self.dbm.delete ( "gallery", "id = %s " % iid )

	#..function:: Gallery.list ( id_gal, kind, ext, start_point, do_count )
	#	Return list for gallery table filtered by params
	#	:param id_gal		gallery id	
	#	:param gal_name	        gallery name
	#	:param kind		Kind of file
	#	:param ext		extension's file
	#	:param start_point	pagination start_point
	#	:param do_count		count tot rows
	def list_imgs ( self, id_gal = 0, gal_name = '', kind = '', ext = '', tag = '' , start_point = 0, do_count = 0 ):
		
		if not id_gal and not gal_name:  return { "rows" : [] }
		
		if not id_gal:
			gal = self.get_gallery ( name = gal_name )
			id_gal = gal [ 'id' ]

		gal_cfg = self._get_cfg ( id_gal = id_gal )
		thumbs =  gal_cfg [ 'IMG_SETTINGS' ][ 1 ]		
		thumb_size = { 'w' : thumbs [ 'width' ], 'h' : thumbs [ 'height' ] }
		sys.stderr.write ( 'thumb size: %s\n\n\n' % repr ( thumb_size ) )
		conds = []
		fields = self.GALLERY_FIELDS
		if id_gal: conds.append ( "id_gal = %s" % id_gal )
		if kind: conds.append ( "kind = '%s'" % kind )
		if ext: conds.append ( "ext = '%s'" % ext )


		"""
		no longer supported
		if tag:
			res = self.liwe.invoke ( "tags.ajax.search", tag_names = tag, module = 'showcase', id_site = site_id )
			if res:
				ids = ','.join ( [ x [ 'id_obj' ] for x in res [ 'tags' ] ] )
				conds.append ( 'id IN ( %s )' % ids )
		"""

		tot_rows = 0
		if do_count:
			tot_rows = self.dbm.count ( "gallery", fields, ",".join ( conds ) )
		res = self.dbm.all_rows ( "gallery", fields, ",".join ( conds ), extras = 'ORDER BY id', debug = self.debug () )
		if not res: 
			res = []

		"""
		no longer supported
		for row in res:
			row [ 'tags' ] = self.liwe.invoke ( "tags.ajax.tags_list", id_obj = row [ "id" ], id_site = site_id, module = 'showcase', names_only = True ) [ 'tags' ]
		"""
		return { "rows" : res, "tot_rows" : tot_rows, "thumb_size" : thumb_size }

	#..function:: Gallery.get_image ( id )
	#	Return corrensponding row of gallery table
	#	:param id	image id
	def get_image ( self, iid = 0 ):
		
		fields = self.GALLERY_FIELDS 
		conds = 'id = %s' % iid
		res = self.dbm.single_row ( [ "gallery" ], fields, conds )
		if not res : return
		return res
